package com.lezai.zookeeper.lock;

import org.I0Itec.zkclient.IZkDataListener;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.CountDownLatch;

public class ZkReadLock extends ZkAbstractLock {
    private String lockPath;
    private String currentPath;
    private String beforePath;

    public ZkReadLock(String lockPath) {
        if (!zkClient.exists(PATH)) {
            zkClient.createPersistent(PATH);
        }
        this.lockPath = PATH + "/" + lockPath;
        if (!zkClient.exists(this.lockPath)) {
            System.out.println("-----------");
            zkClient.createPersistent(this.lockPath);
        }
    }

    public boolean tryLock() {
        if (null == currentPath || currentPath.length() <= 0) {
            currentPath = zkClient.createEphemeralSequential(lockPath + "/read", "lock");
            System.out.println(currentPath);
        }
        List<String> children = zkClient.getChildren(lockPath);

        Collections.sort(children, Comparator.comparingInt(o -> Integer.parseInt(o.replaceAll("[^0-9]*", ""))));
        if (currentPath.equals(lockPath + "/" + children.get(0))) {
//            System.out.println("成功获取锁：" + currentPath);
            return true;
        }
        String key = currentPath.substring(lockPath.length() + 1);
        System.out.println(key);
//        System.out.println("当前孩子"+children.toString());
        int location = children.indexOf(key);
//        System.out.println(location+"读节点位置");
        for (int i=0;i<location;i++){
            System.out.println(children.get(i));
            if (children.get(i).contains("write")){
                this.beforePath = lockPath + "/" + children.get(location - 1);
                System.out.println("获取读锁失败：当前孩子"+children.toString());
                return false;
            }
        }
        return true;
    }

    public void waitLock() {
        CountDownLatch LATCH = new CountDownLatch(1);
        IZkDataListener listener = new IZkDataListener() {
            public void handleDataChange(String s, Object o) {
            }

            public void handleDataDeleted(String s) {
                LATCH.countDown();
            }
        };
        zkClient.subscribeDataChanges(this.beforePath, listener);
        if (!zkClient.exists(this.beforePath)) {
            return;
        }
        try {
            LATCH.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        zkClient.unsubscribeDataChanges(this.beforePath, listener);
    }

    @Override
    public void unLock() {
        System.out.println("成功释放锁"+currentPath);
        zkClient.delete(currentPath);
        super.unLock();
    }
}